<?php
/**
 * 时间工具类
 */
namespace app\libraries\utils;

use app\constdir\SysTime;
use app\libraries\utils\traits\Signleton;

class TimeUtil
{
    use Signleton;

    /**
     * 获取时间段间的时间（小时），左闭右闭
     * @param string $startTime 开始时间，格式：08:00
     * @param string $endTime 结束时间，格式：18:00
     * @return array
     */
    public function timeLenToTwentyFour(string $startTime, string $endTime): array
    {
        if (empty($startTime) || empty($endTime)) {
            return [];
        }
        $startHour = (int)date('H', strtotime($startTime));
        $endHour = (int)date('H', strtotime($endTime));
        $diffTime = (int)bcsub($endHour, $startHour);
        $hour = [];
        for($i = 0; $i <= $diffTime; ++$i) {
            $hour[] = (int)bcadd($startHour, $i);
        }

        return $hour;
    }

    /**
     * 指定时间、天数，获取该时间段的分别是星期几
     * @param int $time 指定时间
     * @param int $len 指定总天数（包函指定时间段）
     * @return array
     * [
     *  5 => [
     *      1672998436,
     *      1673603236
     *  ]
     * ]
     * key 星期几， value = [],包函的具体时间
     */
    public function getWeekByTimeLen(int $time, int $len = 14): array
    {
        // 周数配置
        $weekConfig = [7, 1, 2, 3, 4, 5, 6];

        $week = [];
        for($i = 0; $i < $len; ++$i) {
            $t = strtotime("+{$i} day", $time);
            $week[$weekConfig[date('w', $t)]][] = $t;
        }
        return $week;
    }

    /**
     * 获取时间段-纬度天-向后推
     * @param int $time
     * @param int $timeLen
     * @param int $step
     * @return array
     */
    public function getTimeByDayToAfter(int $time, $timeLen = 60, $step = 1): array
    {
        $unit = SysTime::ONEDAY;
        $i = date('d', $time);
        $diff = $i % $step;

        $timeMax = $time;
        if ($diff > 0) {
            $diff = ($step - $i % $step)  * $unit;
            $timeMax = $time + $diff;
        }

        $num = ceil(bcdiv($timeLen, $step, 1));
        $timeArr = [];
        for($i = 0; $i < $num; $i++) {
            $t = $timeMax + $i * $step * $unit;
            $date = date('Ymd', $t);
            $timeArr[] = $date;
        }

        return $timeArr;
    }

    /**
     * 获取时间段-纬度分-向后推
     * @param int $time
     * @param int $timeLen
     * @param int $step
     * @return array
     */
    public function getTimeByMinuteToAfter(int $time, $timeLen = 60, $step = 5): array
    {
        $i = date('i', $time);

        $diff = $i % $step;
        $timeMax = $time;
        if ($diff > 0) {
            $diff = ($step - $i % $step)  * 60;
            $timeMax = $time + $diff;
        }

        $num = ceil(bcdiv($timeLen, $step, 1));
        $timeArr = [];
        for($i = 0; $i < $num; $i++) {
            $t = $timeMax + $i * $step * 60;
            $date = date('YmdHi', $t) . '00';
            $timeArr[] = $date;
        }

        return $timeArr;
    }

    /**
     * 获取时间段-纬度分-向前推
     * @param int $time
     * @param int $timeLen
     * @param int $step
     * @return array
     */
    public function getTimeByMinuteToFront(int $time, $timeLen = 60, $step = 5): array
    {
        $i = date('i', $time);

        $diff = $i % $step;
        $timeMax = $time;
        if ($diff > 0) {
            $diff = ($step - $i % $step)  * 60;
            $timeMax = $time + $diff;
        }

        $num = ceil(bcdiv($timeLen, $step, 1));
        $timeArr = [];
        for($i = $num; $i > 0; --$i) {
            $t = $timeMax - $i * $step * 60;
            $date = date('YmdHi', $t) . '00';
            $timeArr[] = $date;
        }
        $timeArr[] = date('YmdHi', $timeMax) . '00';

        return $timeArr;
    }

    /**
     * 获取时间段-纬度小时-向前推
     * @param int $time
     * @param int $timeLen
     * @param int $step
     * @return array
     */
    public function getTimeByHourToFront(int $time, $timeLen = 12, $step = 1): array
    {
        $i = date('h', $time);

        $diff = $i % $step;
        $timeMax = $time;
        if ($diff > 0) {
            $diff = ($step - $i % $step) * 60 * 60;
            $timeMax = $time + $diff;
        }

        $num = ceil(bcdiv($timeLen, $step, 1));
        $timeArr = [];
        for($i = $num; $i > 0; --$i) {
            $t = $timeMax - $i * $step * 60 * 60;
            $date = date('YmdH', $t) . '0000';
            $timeArr[] = $date;
        }
        $timeArr[] = date('YmdH', $timeMax) . '0000';

        return $timeArr;
    }

    /**
     * 获取毫秒
     * @return float
     */
    function getMillisecond(): float
    {

        list($s1, $s2) = explode(' ', microtime());

        return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
    }


    /**
     * 获取指定日期区间的所有日期
     *
     * @param $startDate
     * @param $endDate
     * @return array
     */
    public function rangeDate($startDate, $endDate): array
    {
        $startTime = strtotime($startDate);
        $endTime = strtotime($endDate);

        $dateArr = [];
        while ($startTime <= $endTime) {
            $dateArr[] = date('Y-m-d', $startTime);
            $startTime = strtotime('+1 day', $startTime);
        }

        return $dateArr;
    }

    /**
     * 获取指定时间是周几
     *
     * @param $date
     * @return string
     */
    public function getDayOfWeek($date): string
    {
        $weekArray = [
            '周日',
            '周一',
            '周二',
            '周三',
            '周四',
            '周五',
            '周六',
        ];

        return $weekArray[date('w', strtotime($date))];
    }
}
